home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / emulation / frodo / src / iec.asm < prev    next >
Assembly Source File  |  1996-01-29  |  29KB  |  1,463 lines

  1. *
  2. * IEC.asm - IEC-Bus-Routinen, 1541-Emulation
  3. *
  4. * Copyright (C) 1994-1996 by Christian Bauer
  5. *
  6.  
  7. *
  8. * Anmerkungen:
  9. * ------------
  10. *
  11. * Aufrufkonventionen:
  12. *  - Die Routinen IECOut#? und IECIn geben in d0 den Status zurück.
  13. *    Dieser wird von den aufrufenden Routinen mit dem C64-Statusbyte
  14. *    ($90) verodert.
  15. *  - Die Routinen dürfen nur d0-d1/a0-a1 verändern
  16. *
  17. * Funktionsweise:
  18. *  - Am IEC-Bus gibt es drei Sorten von Geräten: Controller, Listener
  19. *    und Talker. Der Controller sind immer wir, zusätzlich können wir
  20. *    wahlweise Talker und Listener sein. Es kann immer nur einen Talker
  21. *    und einen Listener geben (am echten IEC-Bus sind mehrere Listener
  22. *    erlaubt, aber hier nicht).
  23. *  - Die Geräte, die angesprochen werden, sind entweder real am IEC-Kabel
  24. *    oder werden hier emuliert. Für jedes emulierte Laufwerk existiert
  25. *    eine eigene Datenstruktur (Drv?Data). Ein Zeiger darauf wird bei
  26. *    Talk/Listen in TalkerData/ListenerData gespeichert und steht den
  27. *    nachfolgend aufgerufenen Routinen zur Verfügung, damit sich diese
  28. *    um das jeweils angesprochene Laufwerk kümmern.
  29. *  - Bei Geräten am Kabel wird #?Data nicht benutzt, da die Routinen
  30. *    dann die Daten im wesentlichen einfach an den IEC-Bus durchreichen
  31. *
  32. * EOI/EOF:
  33. *  - Im Gegensatz zum Amiga, wo der EOF-Zustand erst nach dem Lesen
  34. *    des letzten Bytes erkannt wird, wird beim IEC-Bus das EOF
  35. *    gleichzeitig mit dem letzten Byte gesendet. Daher verwenden die
  36. *    Leseroutinen einen Puffer, in dem immer ein Byte bereitsteht.
  37. *
  38. * DRVDATA/drv_Type/drv_#?Proc:
  39. *  - Jedem Laufwerk (8-11) ist eine Datenstruktur DRVDATA zugeordnet, die
  40. *    u.a. den Typ des Laufwerks enthält (Amiga-Dateisystem, .d64-Datei,
  41. *    IEC-Kabel).
  42. *  - Je nach Typ werden die sechs Prozedurzeiger drv_InitProc, drv_ExitProc,
  43. *    drv_OpenProc, drv_CloseProc, drv_ReadProc und drv_WriteProc gesetzt, um
  44. *    entweder die Emulation im Amiga-Dateisystem oder in einer .d64-Datei
  45. *    auszuwählen. Nur für Geräte am IEC-Kabel erfolgt die Ein-/Ausgabe
  46. *    direkt hier, für die anderen Typen ist sie in den Include-Files
  47. *    "1541fs.i" und "1541d64.i" gekapselt.
  48. *  - Die drv_#?Proc-Zeiger bilden eine transparente Schnittstelle zur
  49. *    Implementation eines Gerätes (im Prinzip ließe sich so auch eine
  50. *    Druckeremulation einbauen):
  51. *      drv_InitProc bereitet die Emulation vor
  52. *      drv_ExitProc beendet die Emulation
  53. *      drv_OpenProc öffnet einen Kanal
  54. *      drv_CloseProc schließt einen Kanal
  55. *      drv_ReadProc liest aus einem Kanal
  56. *      drv_WriteProc schreibt in einen Kanal
  57. *
  58. * Inkompatibilitäten/Verbesserungen:
  59. *  - Es kann nur ein Listener gleichzeitig aktiv sein
  60. *
  61.  
  62.         MACHINE    68020
  63.  
  64.         INCLUDE    "exec/types.i"
  65.         INCLUDE    "exec/macros.i"
  66.         INCLUDE    "exec/memory.i"
  67.         INCLUDE    "dos/dos.i"
  68.         INCLUDE    "dos/dosasl.i"
  69.         INCLUDE    "resources/misc.i"
  70.         INCLUDE    "hardware/cia.i"
  71.  
  72.         XREF    _SysBase
  73.         XREF    _DOSBase
  74.         XREF    _CiaBase
  75.         XREF    _MiscBase
  76.         XREF    _UtilityBase
  77.  
  78.         XREF    _ciaaprb
  79.         XREF    _ciaaddrb
  80.  
  81.         XREF    _FS_Init    ;1541fs.o
  82.         XREF    _FS_Exit
  83.         XREF    _FS_Open
  84.         XREF    _FS_Close
  85.         XREF    _FS_Read
  86.         XREF    _FS_Write
  87.  
  88.         XREF    _D64_Init    ;1541d64.o
  89.         XREF    _D64_Exit
  90.         XREF    _D64_Open
  91.         XREF    _D64_Close
  92.         XREF    _D64_Read
  93.         XREF    _D64_Write
  94.  
  95.         XDEF    InitIEC
  96.         XDEF    ExitIEC
  97.         XDEF    ChangedIECPrefs
  98.         XDEF    IECOut
  99.         XDEF    IECOutATN
  100.         XDEF    IECOutSec
  101.         XDEF    IECIn
  102.         XDEF    IECSetATN
  103.         XDEF    IECRelATN
  104.         XDEF    IECTurnaround
  105.         XDEF    IECRelease
  106.         XDEF    IECIsOpen
  107.  
  108.         XDEF    Dir8        ;Prefs
  109.         XDEF    Dir9
  110.         XDEF    Dir10
  111.         XDEF    Dir11
  112.         XDEF    Drv8Type
  113.         XDEF    Drv9Type
  114.         XDEF    Drv10Type
  115.         XDEF    Drv11Type
  116.         XDEF    OtherIEC
  117.         XDEF    MapSlash
  118.  
  119.         XREF    PDir8        ;Für ChangedIECPrefs
  120.         XREF    PDir9
  121.         XREF    PDir10
  122.         XREF    PDir11
  123.         XREF    PDrv8Type
  124.         XREF    PDrv9Type
  125.         XREF    PDrv10Type
  126.         XREF    PDrv11Type
  127.  
  128.         SECTION    "text",CODE
  129.  
  130.  
  131. **
  132. ** Definitionen
  133. **
  134.  
  135. ; 1541-Fehlercodes (genauer: Die Nummer des zugeh. Fehlertextes)
  136. ERR_OK        = 0    ;00: OK
  137. ERR_WRITEERROR    = 1    ;25: WRITE ERROR
  138. ERR_WRITEPROTECT = 2    ;26: WRITE PROTECT ON
  139. ERR_SYNTAX30    = 3    ;30: SYNTAX ERROR (Unbekannter Befehl)
  140. ERR_SYNTAX33    = 4    ;33: SYNTAX ERROR (Wildcards beim Schreiben)
  141. ERR_WRITEFILEOPEN = 5    ;60: WRITE FILE OPEN
  142. ERR_FILENOTOPEN    = 6    ;61: FILE NOT OPEN
  143. ERR_FILENOTFOUND = 7    ;62: FILE NOT FOUND
  144. ERR_ILLEGALTS    = 8    ;67: ILLEGAL TRACK OR SECTOR
  145. ERR_NOCHANNEL    = 9    ;70: NO CHANNEL
  146. ERR_STARTUP    = 10    ;73: Einschaltmeldung
  147.  
  148. ; Datenstruktur für ein Laufwerk
  149.  STRUCTURE DRVDATA,0
  150.     BYTE    drv_Type        ;Laufwerks-Typ (DRTYPE_*)
  151.     BYTE    drv_ReadChar        ;Byte-Puffer zum Lesen aus Dateien
  152.     BYTE    drv_NameLen        ;Bisher empfangene Länge des Dateinamens
  153.     BYTE    drv_ErrorLen        ;Restliche Länge der Fehlermeldung
  154.     APTR    drv_NamePtr        ;Zeiger in Dateinamen, für Open/IECOut
  155.     APTR    drv_ErrorPtr        ;Zeiger in Fehlermeldung
  156.     APTR    drv_Lock        ;Lock des Verzeichnisses des Laufwerks
  157.                     ; bzw. Handle der .d64-Datei
  158.  
  159.                     ;Prozeduren:
  160.     APTR    drv_InitProc        ; Initialisieren
  161.     APTR    drv_ExitProc        ; Beenden
  162.     APTR    drv_OpenProc        ; Kanal öffnen
  163.     APTR    drv_CloseProc        ; Kanal schließen
  164.     APTR    drv_ReadProc        ; Byte lesen
  165.     APTR    drv_WriteProc        ; Byte schreiben
  166.  
  167.     STRUCT    drv_CmdBuffer,44    ;Eingabepuffer für Kommandos
  168.     LONG    drv_CmdLen        ;Länge des bisher empfangenen Kommandos
  169.  
  170.     STRUCT    drv_Handle,16*4        ;FS: FileHandles für alle 16 Kanäle
  171.  
  172.     STRUCT    drv_ChanMode,16        ;D64: Kanalmodus
  173.     STRUCT    drv_ChanBufNum,16    ;D64: Nummer des Puffers des Kanals
  174.     STRUCT    drv_ChanBuf,16*4    ;D64: Zeiger auf Puffer des Kanals
  175.     STRUCT    drv_BufPtr,16*4        ;D64: Aktuelle Position im Puffer
  176.     STRUCT    drv_BufLen,16*4        ;D64: Restliche Anzahl Bytes im Puffer
  177.  
  178.     APTR    drv_RAM            ;D64: 2KB RAM für das Laufwerk
  179.     STRUCT    drv_BufFree,4        ;D64: Puffer 0..3 frei?
  180.  
  181.     LONG    drv_ImageHeader        ;D64: Länge des Headers der Image-Datei (.d64: 0, .x64: 64)
  182.  
  183.     APTR    drv_BAM            ;D64: Zeiger auf Puffer für BAM (Puffer 4, $700)
  184.     STRUCT    drv_DIR,256        ;D64: Temporärer Puffer zum Directory-Lesen und -Scannen
  185.  LABEL drv_SIZEOF
  186.  
  187. ; Drv?Type
  188. DRTYPE_DIR    = 0    ;1541-Emulation in Amiga-Verzeichnis
  189. DRTYPE_D64    = 1    ;1541-Emulation in .d64-Datei
  190. DRTYPE_IEC    = 2    ;Echte 1541 am IEC-Kabel
  191.  
  192. ; C64-Status-Codes
  193. ST_OK        = 0    ;Alles klar
  194. ST_READ_TIMEOUT    = $02    ;Timeout beim Lesen
  195. ST_TIMEOUT    = $03    ;Timeout
  196. ST_EOF        = $40    ;End of file
  197. ST_NOTPRESENT    = $80    ;Device not present
  198.  
  199. ; IEC-Befehlscodes
  200. CMD_DATA    = $60
  201. CMD_CLOSE    = $e0
  202. CMD_OPEN    = $f0
  203.  
  204. ; Länge des Namenspuffers, muß zwischen 32 und 256 liegen
  205. NAMEBUF_LENGTH    = 256
  206.  
  207. ; Makros für IEC-Kabel
  208. DATA_HI        MACRO
  209.         bclr    #5,_ciaaprb
  210.         ENDM
  211.  
  212. DATA_LO        MACRO
  213.         bset    #5,_ciaaprb
  214.         ENDM
  215.  
  216. CLOCK_HI    MACRO
  217.         bclr    #4,_ciaaprb
  218.         ENDM
  219.  
  220. CLOCK_LO    MACRO
  221.         bset    #4,_ciaaprb
  222.         ENDM
  223.  
  224. ATN_HI        MACRO
  225.         bclr    #3,_ciaaprb
  226.         ENDM
  227.  
  228. ATN_LO        MACRO
  229.         bset    #3,_ciaaprb
  230.         ENDM
  231.  
  232. LINE_RELEASE    MACRO
  233.         ATN_HI
  234.         bsr    Wait40us
  235.         CLOCK_HI
  236.         DATA_HI
  237.         ENDM
  238.  
  239. ; Data -> Carry, Clock -> Negative
  240. GET_DATA_CLOCK    MACRO
  241. \@1$        move.b    _ciaaprb,d0
  242.         cmp.b    _ciaaprb,d0
  243.         bne    \@1$
  244.         add.b    d0,d0
  245.         ENDM
  246.  
  247. WAIT_CLOCK_HI    MACRO
  248. \@1$        GET_DATA_CLOCK
  249.         bpl    \@1$
  250.         ENDM
  251.  
  252. WAIT_CLOCK_LO    MACRO
  253. \@1$        GET_DATA_CLOCK
  254.         bmi    \@1$
  255.         ENDM
  256.  
  257. WAIT_DATA_HI    MACRO
  258. \@1$        GET_DATA_CLOCK
  259.         bcc    \@1$
  260.         ENDM
  261.  
  262. WAIT_DATA_LO    MACRO
  263. \@1$        GET_DATA_CLOCK
  264.         bcs    \@1$
  265.         ENDM
  266.  
  267.  
  268. **
  269. ** IEC-Emulation starten
  270. **
  271. ** Rückgabe: d0=0 Alles OK
  272. **           d0=1 Parallelport belegt
  273. **           d0=2 Kein Timer frei
  274. **
  275.  
  276. ; Emulation aller 4 Laufwerke vorbereiten
  277. InitIEC        lea    Drv8Data,a0
  278.         move.w    Drv8Type,d0
  279.         bsr    SetDrvProcs
  280.  
  281.         pea    Dir8
  282.         pea    Drv8Data
  283.         move.l    Drv8Data+drv_InitProc,a0
  284.         jsr    (a0)
  285.         addq.l    #8,sp
  286.  
  287.         lea    Drv9Data,a0
  288.         move.w    Drv9Type,d0
  289.         bsr    SetDrvProcs
  290.  
  291.         pea    Dir9
  292.         pea    Drv9Data
  293.         move.l    Drv9Data+drv_InitProc,a0
  294.         jsr    (a0)
  295.         addq.l    #8,sp
  296.  
  297.         lea    Drv10Data,a0
  298.         move.w    Drv10Type,d0
  299.         bsr    SetDrvProcs
  300.  
  301.         pea    Dir10
  302.         pea    Drv10Data
  303.         move.l    Drv10Data+drv_InitProc,a0
  304.         jsr    (a0)
  305.         addq.l    #8,sp
  306.  
  307.         lea    Drv11Data,a0
  308.         move.w    Drv11Type,d0
  309.         bsr    SetDrvProcs
  310.  
  311.         pea    Dir11
  312.         pea    Drv11Data
  313.         move.l    Drv11Data+drv_InitProc,a0
  314.         jsr    (a0)
  315.         addq.l    #8,sp
  316.  
  317. ; Flag setzen
  318.         st.b    IECInited
  319.  
  320. ; Resourcen für das IEC-Kabel belegen, wenn nötig
  321.         bra    CheckCablePrefs
  322.  
  323.  
  324. **
  325. ** IEC-Emulation beenden
  326. **
  327.  
  328. ; Resourcen des IEC-Kabels freigeben
  329. ExitIEC        bsr    CloseIECBus
  330.  
  331. ; Emulation aller 4 Laufwerke beenden
  332.         tst.b    IECInited
  333.         beq    1$
  334.  
  335.         pea    Drv8Data
  336.         move.l    Drv8Data+drv_ExitProc,a0
  337.         jsr    (a0)
  338.         addq.l    #4,sp
  339.  
  340.         pea    Drv9Data
  341.         move.l    Drv9Data+drv_ExitProc,a0
  342.         jsr    (a0)
  343.         addq.l    #4,sp
  344.  
  345.         pea    Drv10Data
  346.         move.l    Drv10Data+drv_ExitProc,a0
  347.         jsr    (a0)
  348.         addq.l    #4,sp
  349.  
  350.         pea    Drv11Data
  351.         move.l    Drv11Data+drv_ExitProc,a0
  352.         jsr    (a0)
  353.         addq.l    #4,sp
  354. 1$
  355.  
  356. ; Temporäre Datei löschen
  357.         move.l    _DOSBase,a6
  358.         move.l    #TempFileName,d1
  359.         JMPLIB    DeleteFile
  360.  
  361.  
  362. **
  363. ** IEC-Einstellungen wurden verändert
  364. ** Rückgabe: d0=0 Alles OK
  365. **           d0=1 Parallelport belegt
  366. **           d0=2 Kein Timer frei
  367. **
  368.  
  369. ; Laufwerke schließen und neu öffnen, wenn sich die Einstellungen geändert haben
  370. ChangedIECPrefs    lea    Drv8Data,a3
  371.         lea    Dir8,a4
  372.         lea    PDir8,a5
  373.         move.w    PDrv8Type,d4
  374.         bsr    DrvReInit
  375.  
  376.         lea    Drv9Data,a3
  377.         lea    Dir9,a4
  378.         lea    PDir9,a5
  379.         move.w    PDrv9Type,d4
  380.         bsr    DrvReInit
  381.  
  382.         lea    Drv10Data,a3
  383.         lea    Dir10,a4
  384.         lea    PDir10,a5
  385.         move.w    PDrv10Type,d4
  386.         bsr    DrvReInit
  387.  
  388.         lea    Drv11Data,a3
  389.         lea    Dir11,a4
  390.         lea    PDir11,a5
  391.         move.w    PDrv11Type,d4
  392.         bsr    DrvReInit
  393.  
  394. ; Einstellungen übertragen
  395. CheckCablePrefs    moveq    #0,d1
  396.  
  397.         cmp.w    #DRTYPE_IEC,PDrv8Type
  398.         seq    d0
  399.         or.b    d0,d1
  400.  
  401.         cmp.w    #DRTYPE_IEC,PDrv9Type
  402.         seq    d0
  403.         or.b    d0,d1
  404.  
  405.         cmp.w    #DRTYPE_IEC,PDrv10Type
  406.         seq    d0
  407.         or.b    d0,d1
  408.  
  409.         cmp.w    #DRTYPE_IEC,PDrv11Type
  410.         seq    d0
  411.         or.b    d0,d1
  412.  
  413.         or.w    OtherIEC,d1    ;d1: Flag: IEC-Kabel wird benötigt
  414.  
  415. ; IEC öffnen, wenn mindestens ein Gerät mit IEC laufen soll,
  416. ; sonst schließen
  417.         tst.b    d1
  418.         beq    CloseIECBus
  419.         bra    OpenIECBus
  420.  
  421.  
  422. *
  423. * Auf Benutzung des IEC-Kabels vorbereiten
  424. * Rückgabe: d0=0 Alles OK
  425. *           d0=1 Parallelport belegt
  426. *           d0=2 Kein Timer frei
  427. *
  428.  
  429. OpenIECBus    move.l    a6,-(sp)
  430.         tst.b    IECIsOpen    ;Kann auch mehrmals aufgerufen werden
  431.         bne    OIECOK
  432.  
  433. ; Parallelport belegen
  434.         move.l    _MiscBase,d0
  435.         beq    OIECNoPort
  436.         move.l    d0,a6
  437.         moveq    #MR_PARALLELPORT,d0
  438.         lea    ParPortName,a1
  439.         JSRLIB    AllocMiscResource
  440.         tst.l    d0
  441.         bne    OIECNoPort
  442.  
  443.         move.b    #$00,_ciaaprb    ;Port inaktiv
  444.         move.b    #$38,_ciaaddrb    ;DDR konfigurieren
  445.  
  446. ; Timer A belegen
  447.         move.l    _CiaBase,a6
  448.         lea    TimerInterrupt,a1
  449.         moveq    #CIAICRB_TA,d0
  450.         JSRLIB    AddICRVector
  451.         tst.l    d0
  452.         bne    1$
  453.  
  454. ; Gelungen
  455.         move.b    #CIAICRB_TA,WhichTimer
  456.         move.b    #CIAICRF_TA,WhichTimerMask
  457.         move.l    #$bfe401,CiaTimerReg
  458.         move.l    #$bfee01,CiaControlReg
  459.         bra    3$
  460.  
  461. ; Nicht gelungen, dann Timer B probieren
  462. 1$        lea    TimerInterrupt,a1
  463.         moveq    #CIAICRB_TB,d0
  464.         JSRLIB    AddICRVector
  465.         tst.l    d0
  466.         bne    2$
  467.  
  468. ; Gelungen
  469.         move.b    #CIAICRB_TB,WhichTimer
  470.         move.b    #CIAICRF_TB,WhichTimerMask
  471.         move.l    #$bfe601,CiaTimerReg
  472.         move.l    #$bfef01,CiaControlReg
  473.         bra    3$
  474.  
  475. ; Nicht gelungen, dann Parallelport wieder freigeben
  476. 2$        move.b    #$00,_ciaaddrb    ;Port auf Eingabe
  477.  
  478.         move.l    _MiscBase,a6
  479.         moveq    #MR_PARALLELPORT,d0
  480.         JSRLIB    FreeMiscResource
  481.  
  482.         moveq    #2,d0        ;Kein Timer frei
  483.         move.l    (sp)+,a6
  484.         rts
  485.  
  486. ; Alles klar, Timer-Interrupt abschalten und Timer stoppen
  487. 3$        move.b    WhichTimerMask,d0
  488.         JSRLIB    AbleICR
  489.  
  490.         move.l    CiaControlReg,a0
  491.         and.b    #$80,(a0)
  492.  
  493.         st.b    IECIsOpen
  494. OIECOK        moveq    #0,d0        ;Alles OK
  495.         move.l    (sp)+,a6
  496.         rts
  497.  
  498. OIECNoPort    moveq    #1,d0        ;Parallelport belegt
  499.         move.l    (sp)+,a6
  500.         rts
  501.  
  502.  
  503. *
  504. * Benutzung des IEC-Kabels beenden
  505. * Rückgabe: d0=0
  506. *
  507.  
  508. CloseIECBus    tst.b    IECIsOpen
  509.         beq    1$
  510.  
  511.         move.b    #$00,_ciaaddrb    ;Port auf Eingabe
  512.  
  513.         move.l    a6,-(sp)    ;Parallelport freigeben
  514.         move.l    _MiscBase,a6
  515.         moveq    #MR_PARALLELPORT,d0
  516.         JSRLIB    FreeMiscResource
  517.  
  518.         move.l    CiaControlReg,a0 ;Timer stoppen
  519.         and.b    #$80,(a0)
  520.  
  521.         move.l    _CiaBase,a6
  522.         lea    TimerInterrupt,a1
  523.         move.b    WhichTimer,d0
  524.         JSRLIB    RemICRVector
  525.  
  526.         move.l    (sp)+,a6
  527.         clr.b    IECIsOpen
  528.  
  529. 1$        moveq    #0,d0
  530.         rts
  531.  
  532.  
  533. *
  534. * Laufwerk neu initialisieren, falls nötig
  535. *
  536. * a3.l: Zeiger auf DRVDATA
  537. * a4.l: Alter Verzeichnis-String
  538. * a5.l: Neuer Verzeichnis-String
  539. * d4.w: Neues Drv?Type
  540. *
  541.  
  542. DrvReInit    move.l    _UtilityBase,a6
  543.  
  544.         move.l    a4,a0        ;Hat sich das Verzeichnis/die Datei geändert?
  545.         move.l    a5,a1
  546.         move.l    #255,d0
  547.         JSRLIB    Strnicmp
  548.         tst.l    d0
  549.         bne    1$
  550.  
  551.         cmp.b    drv_Type(a3),d4    ;Nein, hat sich der Typ geändert?
  552.         beq    2$
  553.  
  554. 1$        move.l    a3,-(sp)    ;Ja, Exit aufrufen
  555.         move.l    drv_ExitProc(a3),a0
  556.         jsr    (a0)
  557.         addq.l    #4,sp
  558.  
  559.         move.l    a3,a0        ;Neue Prozeduren setzen
  560.         move.w    d4,d0
  561.         bsr    SetDrvProcs
  562.  
  563.         move.l    a5,-(sp)    ;Und neues Init aufrufen
  564.         move.l    a3,-(sp)
  565.         move.l    drv_InitProc(a3),a0
  566.         jsr    (a0)
  567.         addq.l    #8,sp
  568. 2$        rts
  569.  
  570.  
  571. *
  572. * Prozeduren in DRVDATA je nach Typ setzen
  573. *
  574. * a0.l: Zeiger auf DRVDATA
  575. * d0.w: Drv?Type
  576. *
  577.  
  578. SetDrvProcs    move.b    d0,drv_Type(a0)        ;Typ setzen
  579.  
  580.         cmp.w    #DRTYPE_D64,d0
  581.         beq    1$
  582.  
  583.         move.l    #_FS_Init,drv_InitProc(a0)
  584.         move.l    #_FS_Exit,drv_ExitProc(a0)
  585.         move.l    #_FS_Open,drv_OpenProc(a0)
  586.         move.l    #_FS_Close,drv_CloseProc(a0)
  587.         move.l    #_FS_Read,drv_ReadProc(a0)
  588.         move.l    #_FS_Write,drv_WriteProc(a0)
  589.         rts
  590.  
  591. 1$        move.l    #_D64_Init,drv_InitProc(a0)
  592.         move.l    #_D64_Exit,drv_ExitProc(a0)
  593.         move.l    #_D64_Open,drv_OpenProc(a0)
  594.         move.l    #_D64_Close,drv_CloseProc(a0)
  595.         move.l    #_D64_Read,drv_ReadProc(a0)
  596.         move.l    #_D64_Write,drv_WriteProc(a0)
  597.         rts
  598.  
  599.  
  600. **
  601. ** IECOut - Ein Byte ausgeben
  602. ** d0.b: Byte
  603. ** d1.b: <0: EOI-Flag
  604. **
  605.  
  606. IECOut        tst.b    ListenerIsIEC    ;Listener am IEC-Kabel?
  607.         bne    IECByteOut    ;Ja, dann Byte über Kabel senden
  608.         tst.b    ListenerActive    ;Wurde ein Gerät angesprochen?
  609.         beq    1$
  610.  
  611.         cmp.b    #CMD_OPEN,ReceivedCmd
  612.         beq    OpenOut
  613.         cmp.b    #CMD_DATA,ReceivedCmd
  614.         beq    DataOut
  615.  
  616. 1$        move.b    #ST_TIMEOUT,d0    ;Kein Listener aktiv oder kein gültiger Befehl
  617.         rts
  618.  
  619.  
  620. **
  621. ** IECOutATN - Ein Byte mit ATN ausgeben (Talk/Listen/Untalk/Unlisten)
  622. ** d0.b: Byte
  623. **
  624.  
  625. IECOutATN    clr.b    SecAddr        ;Befehl kommt mit der Sekundäradresse danach
  626.         clr.b    ReceivedCmd
  627.  
  628.         move.b    d0,d1
  629.         and.b    #$0f,d0        ;d0.b: Gerätenummer
  630.         and.b    #$f0,d1        ;d1.b: Funktion
  631.  
  632.         st.b    Listening    ;Funktion auswerten
  633.         cmp.b    #$20,d1        ;Bei Listen ist das Flag Listening gesetzt
  634.         beq    Listen
  635.         clr.b    Listening
  636.         cmp.b    #$30,d1
  637.         beq    Unlisten
  638.         cmp.b    #$40,d1
  639.         beq    Talk
  640.         cmp.b    #$50,d1
  641.         beq    Untalk
  642.  
  643.         move.b    #ST_TIMEOUT,d0    ;Ungültige Funktion
  644.         rts
  645.  
  646.  
  647. **
  648. ** IECOutSec - Sekundäradresse ausgeben
  649. ** d0.b: Sekundäradresse
  650. **
  651.  
  652. IECOutSec    tst.b    Listening    ;Nach Listen oder nach Talk?
  653.         beq    1$
  654.  
  655.         tst.b    ListenerIsIEC    ;Nach Listen: Listener am IEC-Kabel?
  656.         bne    IECByteOutSec
  657.         tst.b    ListenerActive    ;Wurde ein Gerät angesprochen?
  658.         beq    2$
  659.  
  660.         move.b    d0,d1
  661.         and.b    #$0f,d0        ;Sekundäradresse
  662.         move.b    d0,SecAddr
  663.         and.b    #$f0,d1        ;und Befehlscode speichern
  664.         move.b    d1,ReceivedCmd
  665.         bra    SecListen    ;Sek.adr nach Listen
  666.  
  667. 1$        tst.b    TalkerIsIEC    ;Nach Talk: Talker am IEC-Kabel?
  668.         bne    IECByteOutSec
  669.         tst.b    TalkerActive    ;Wurde ein Gerät angesprochen?
  670.         beq    2$
  671.  
  672.         move.b    d0,d1
  673.         and.b    #$0f,d0        ;Sekundäradresse
  674.         move.b    d0,SecAddr
  675.         and.b    #$f0,d1        ;und Befehlscode speichern
  676.         move.b    d1,ReceivedCmd
  677.         bra    SecTalk        ;Sek.adr nach Talk
  678.  
  679. 2$        move.b    #ST_TIMEOUT,d0    ;Es erfolgte kein Listen/Talk
  680.         rts
  681.  
  682.  
  683. **
  684. ** IECIn - Ein Byte einlesen
  685. ** RÜckgabe: d1.b: Byte
  686. **
  687.  
  688. IECIn        tst.b    TalkerIsIEC    ;Talker am IEC-Kabel?
  689.         bne    IECByteIn
  690.         tst.b    TalkerActive    ;Wurde ein Gerät angesprochen?
  691.         beq    1$
  692.  
  693.         cmp.b    #CMD_DATA,ReceivedCmd
  694.         beq    DataIn
  695.  
  696. 1$        move.b    #ST_TIMEOUT,d0    ;Kein Talk bzw. kein CMD_DATA
  697.         clr.b    d1
  698.         rts
  699.  
  700.  
  701. **
  702. ** IECSetATN - ATN setzen (für Untalk)
  703. **
  704.  
  705. IECSetATN    tst.b    TalkerIsIEC    ;Nur bei IEC-Geräten etwas machen
  706.         beq    1$
  707.         CLOCK_LO
  708.         ATN_LO
  709. 1$        rts
  710.  
  711.  
  712. **
  713. ** IECRelATN - ATN wegnehmen
  714. **
  715.  
  716. IECRelATN    tst.b    IECIsOpen
  717.         beq    1$
  718.         ATN_HI
  719.         bsr    Wait20us
  720. 1$        rts
  721.  
  722.  
  723. **
  724. ** IECTurnaround - Talk-attention turn around
  725. **
  726.  
  727. IECTurnaround    tst.b    TalkerIsIEC    ;Nur bei IEC-Geräten etwas machen
  728.         beq    1$
  729.         move.l    a6,-(sp)
  730.         move.l    _SysBase,a6
  731.         JSRLIB    Disable
  732.         DATA_LO
  733.         bsr    Wait20us
  734.         ATN_HI
  735.         CLOCK_HI
  736.         WAIT_CLOCK_LO
  737.         bsr    Wait60us
  738.         JSRLIB    Enable
  739.         move.l    (sp)+,a6
  740. 1$        rts
  741.  
  742.  
  743. **
  744. ** IECRelease - System line release
  745. **
  746.  
  747. IECRelease    tst.b    IECIsOpen
  748.         beq    1$
  749.         LINE_RELEASE
  750. 1$        rts
  751.  
  752.  
  753. *
  754. * Listen
  755. * d0.b: Gerätenummer
  756. * d1.b: Funktion
  757. *
  758.  
  759. Listen        cmp.b    #8,d0        ;Gerät zwischen 8 und 11?
  760.         blo    ListenOther
  761.         cmp.b    #11,d0
  762.         bhi    ListenOther
  763.  
  764.         moveq    #0,d1        ;Ja, Zeiger auf Datenbereich holen
  765.         move.b    d0,d1
  766.         subq.b    #8,d1
  767.         move.l    (DrvTab,d1.w*4),a0
  768.         cmp.b    #DRTYPE_IEC,drv_Type(a0) ;IEC-Gerät?
  769.         beq    ListenIEC
  770.         tst.l    drv_Lock(a0)    ;Nein, Verzeichnis vorhanden?
  771.         beq    ListenNotPr
  772.  
  773.         move.l    a0,ListenerData    ;Ja, Zeiger auf Datenbereich sichern
  774.         st.b    ListenerActive    ;Listener ist aktiv
  775.         clr.b    ListenerIsIEC
  776.         moveq    #ST_OK,d0
  777.         rts
  778.  
  779. ; Anderes Gerät außer 8..11
  780. ListenOther    tst.w    OtherIEC
  781.         beq    ListenNotPr
  782.  
  783. ; Listen über IEC-Kabel
  784. ListenIEC    move.l    a0,ListenerData    ;Zeiger auf Datenbereich sichern
  785.  
  786.         moveq    #$20,d1        ;Listen über Kabel senden
  787.         bsr    IECByteOutATN
  788.         cmp.b    #ST_NOTPRESENT,d0
  789.         beq    ListenNotPr
  790.         st.b    ListenerIsIEC    ;Gelungen, Listener ist aktiv
  791.         rts
  792.  
  793. ; Gerät nicht vorhanden
  794. ListenNotPr    move.b    #ST_NOTPRESENT,d0
  795.         clr.b    ListenerActive
  796.         clr.b    ListenerIsIEC
  797.         rts
  798.  
  799.  
  800. *
  801. * Talk
  802. * d0.b: Gerätenummer
  803. * d1.b: Funktion
  804. *
  805.  
  806. Talk        cmp.b    #8,d0        ;Gerät zwischen 8 und 11?
  807.         blo    TalkOther
  808.         cmp.b    #11,d0
  809.         bhi    TalkOther
  810.  
  811.         moveq    #0,d1        ;Ja, Zeiger auf Datenbereich holen
  812.         move.b    d0,d1
  813.         subq.b    #8,d1
  814.         move.l    (DrvTab,d1.w*4),a0
  815.         cmp.b    #DRTYPE_IEC,drv_Type(a0) ;IEC-Gerät?
  816.         beq    TalkIEC
  817.         tst.l    drv_Lock(a0)    ;Nein, Verzeichnis vorhanden?
  818.         beq    TalkNotPr
  819.  
  820.         move.l    a0,TalkerData    ;Ja, Zeiger auf Datenbereich sichern
  821.         st.b    TalkerActive    ;Talker ist aktiv
  822.         clr.b    TalkerIsIEC
  823.         moveq    #ST_OK,d0
  824.         rts
  825.  
  826. ; Anderes Gerät außer 8..11
  827. TalkOther    tst.w    OtherIEC
  828.         beq    TalkNotPr
  829.  
  830. ; Talk über IEC-Kabel
  831. TalkIEC        move.l    a0,TalkerData    ;Zeiger auf Datenbereich sichern
  832.  
  833.         moveq    #$40,d1        ;Talk über Kabel senden
  834.         bsr    IECByteOutATN
  835.         cmp.b    #ST_NOTPRESENT,d0
  836.         beq    TalkNotPr
  837.         st.b    TalkerIsIEC    ;Gelungen, Talker ist aktiv
  838.         rts
  839.  
  840. ; Gerät nicht vorhanden
  841. TalkNotPr    move.b    #ST_NOTPRESENT,d0
  842.         clr.b    TalkerActive
  843.         clr.b    TalkerIsIEC
  844.         rts
  845.  
  846.  
  847. *
  848. * Unlisten
  849. * d0.b: Gerätenummer
  850. * d1.b: Funktion
  851. *
  852.  
  853. Unlisten    tst.b    ListenerIsIEC    ;Listener am IEC-Kabel?
  854.         beq    1$
  855.         bsr    IECByteOutATN    ;Ja, Unlisten über Kabel senden
  856.         bra    2$
  857.  
  858. 1$        moveq    #ST_OK,d0
  859. 2$        clr.b    ListenerActive    ;Gerät nicht mehr aktiv
  860.         clr.b    ListenerIsIEC
  861.         rts
  862.  
  863. *
  864. * Untalk
  865. * d0.b: Gerätenummer
  866. * d1.b: Funktion
  867. *
  868.  
  869. Untalk        tst.b    TalkerIsIEC    ;Talker am IEC-Kabel?
  870.         beq    1$
  871.         bsr    IECByteOutATN    ;Ja, Untalk über Kabel senden
  872.         bra    2$
  873.  
  874. 1$        moveq    #ST_OK,d0
  875. 2$        clr.b    TalkerActive    ;Gerät nicht mehr aktiv
  876.         clr.b    TalkerIsIEC
  877.         rts
  878.  
  879.  
  880. *
  881. * SecListen - Sekundäradresse nach Listen
  882. * d0.b: Sekundäradresse
  883. * d1.b: Befehlscode
  884. *
  885.  
  886. SecListen    cmp.b    #CMD_OPEN,d1
  887.         beq    SecListenOpen
  888.         cmp.b    #CMD_CLOSE,d1
  889.         beq    SecListenClose
  890.  
  891.         moveq    #ST_OK,d0
  892.         rts
  893.  
  894.  
  895. *
  896. * Open-Befehl: Auf Empfang des Dateinamens vorbereiten
  897. *
  898.  
  899. SecListenOpen    move.l    ListenerData,a0
  900.         move.l    #NameBuf,drv_NamePtr(a0)
  901.         clr.b    drv_NameLen(a0)
  902.         moveq    #ST_OK,d0
  903.         rts
  904.  
  905.  
  906. *
  907. * Close-Befehl: Kanal schließen
  908. *
  909.  
  910. SecListenClose    move.l    ListenerData,a0
  911.         moveq    #0,d0
  912.         move.b    SecAddr,d0
  913.         move.l    d0,-(sp)
  914.         move.l    a0,-(sp)
  915.         move.l    drv_CloseProc(a0),a0
  916.         jsr    (a0)
  917.         addq.l    #8,sp
  918.         rts
  919.  
  920.  
  921. *
  922. * SecTalk - Sekundäradresse nach Talk
  923. * d0.b: Sekundäradresse
  924. * d1.b: Befehlscode
  925. *
  926.  
  927. SecTalk        moveq    #ST_OK,d0
  928.         rts
  929.  
  930.  
  931. *
  932. * Byte nach Open-Befehl: Zeichen im Dateinamen speichern, bei EOI Datei öffnen
  933. * d0.b: Byte
  934. * d1.b: EOI-Flag
  935. *
  936.  
  937. OpenOut        move.l    ListenerData,a0
  938.         cmp.b    #NAMEBUF_LENGTH-1,drv_NameLen(a0) ;Noch genügend Platz im NameBuffer?
  939.         bhs    2$
  940.         move.l    drv_NamePtr(a0),a1    ;Ja, Zeichen speichern
  941.         move.b    d0,(a1)+
  942.         move.l    a1,drv_NamePtr(a0)
  943.         addq.b    #1,drv_NameLen(a0)
  944.  
  945. 2$        tst.b    d1            ;EOI?
  946.         bpl    1$
  947.  
  948.         move.l    ListenerData,a0        ;Ja, Datei öffnen
  949.         move.l    drv_NamePtr(a0),a1    ;Dateiname mit Nullbyte abschließen
  950.         clr.b    (a1)
  951.         pea    NameBuf
  952.         moveq    #0,d0
  953.         move.b    SecAddr,d0
  954.         move.l    d0,-(sp)
  955.         move.l    a0,-(sp)
  956.         move.l    drv_OpenProc(a0),a0
  957.         jsr    (a0)
  958.         lea    12(sp),sp
  959.  
  960. 1$        moveq    #ST_OK,d0
  961.         rts
  962.  
  963.  
  964. *
  965. * Zeichen aus Datenkanal lesen
  966. * RÜckgabe: d1.b: Byte
  967. *
  968.  
  969. DataIn        move.l    TalkerData,a0
  970.         moveq    #0,d0
  971.         move.b    SecAddr,d0
  972.         pea    DataInBuf
  973.         move.l    d0,-(sp)
  974.         move.l    a0,-(sp)
  975.         move.l    drv_ReadProc(a0),a0
  976.         jsr    (a0)
  977.         lea    12(sp),sp
  978.         move.b    DataInBuf,d1
  979.         rts
  980.  
  981.  
  982. *
  983. * Byte nach Data-Befehl: Zeichen in Datei schreiben
  984. * d0.b: Byte
  985. * d1.b: EOI-Flag
  986. *
  987.  
  988. DataOut        move.l    ListenerData,a0
  989.         move.l    d1,-(sp)
  990.         move.l    d0,-(sp)
  991.         moveq    #0,d0
  992.         move.b    SecAddr,d0
  993.         move.l    d0,-(sp)
  994.         move.l    a0,-(sp)
  995.         move.l    drv_WriteProc(a0),a0
  996.         jsr    (a0)
  997.         lea    16(sp),sp
  998.         rts
  999.  
  1000.  
  1001. *
  1002. * Byte mit ATN über IEC-Kabel senden
  1003. * d0.b: Gerätenummer
  1004. * d1.b: Funktion
  1005. *
  1006.  
  1007. IECByteOutATN    tst.b    IECIsOpen
  1008.         bne    1$
  1009.         move.b    #ST_NOTPRESENT,d0
  1010.         rts
  1011.  
  1012. 1$        movem.l    d2/d7/a6,-(sp)
  1013.         move.b    d0,d2
  1014.         or.b    d1,d2        ;d2: Auszugebendes Byte
  1015.  
  1016.         move.l    _SysBase,a6
  1017.         JSRLIB    Disable
  1018.  
  1019.         DATA_HI
  1020.         ATN_LO
  1021.         bra    IECByteOutSec2    ;ATN response abwarten und Byte ausgeben
  1022.  
  1023.  
  1024. *
  1025. * Sekundäradresse über IEC-Kabel senden
  1026. * d0.b: Sekundäradresse
  1027. *
  1028.  
  1029. IECByteOutSec    tst.b    IECIsOpen
  1030.         bne    1$
  1031.         move.b    #ST_NOTPRESENT,d0
  1032.         rts
  1033.  
  1034. 1$        movem.l    d2/d7/a6,-(sp)
  1035.         move.b    d0,d2        ;d2: Auszugebendes Byte
  1036.  
  1037.         move.l    _SysBase,a6
  1038.         JSRLIB    Disable
  1039.  
  1040. IECByteOutSec2    CLOCK_LO
  1041.         DATA_HI
  1042.         bsr    Wait1ms        ;Max ATN response abwarten
  1043.         moveq    #0,d1        ;Kein EOI
  1044.         bra    IECByteOut2    ;Byte ausgeben
  1045.  
  1046.  
  1047. *
  1048. * Byte über IEC-Kabel senden
  1049. * d0.b: Byte
  1050. * d1.b: EOI-Flag
  1051. *
  1052.  
  1053. IECByteOut    tst.b    IECIsOpen
  1054.         bne    1$
  1055.         move.b    #ST_NOTPRESENT,d0
  1056.         rts
  1057.  
  1058. 1$        movem.l    d2/d7/a6,-(sp)
  1059.         move.b    d0,d2        ;d2: Auszugebendes Byte
  1060.  
  1061.         move.l    _SysBase,a6
  1062.         JSRLIB    Disable
  1063.  
  1064. ; Übertragung einleiten
  1065. IECByteOut2    move.b    d1,d7        ;d7: EOI-Flag
  1066.         DATA_HI
  1067.         GET_DATA_CLOCK        ;Data bleibt high -> Device not present
  1068.         bcs    IBODevNotPr
  1069.         CLOCK_HI        ;Talker ready
  1070.  
  1071.         WAIT_DATA_HI        ;Warten auf Listener ready for data
  1072.  
  1073.         tst.b    d7        ;EOI?
  1074.         bpl    1$
  1075.  
  1076.         WAIT_DATA_LO        ;Ja, EOI-Handshake abwarten
  1077.         WAIT_DATA_HI
  1078.  
  1079. 1$        CLOCK_LO        ;Talker sending
  1080.  
  1081.         bsr    Wait40us    ;Wichtige Verzögerung, aber wozu?
  1082.  
  1083. ; 8 Bits übertragen
  1084.         moveq    #7,d7        ;d7: Bitzähler
  1085. IBOBitLoop    GET_DATA_CLOCK        ;Data low -> Time out
  1086.         bcc    IBOTimeOut
  1087.  
  1088.         lsr.b    #1,d2        ;Nächstes Bit holen
  1089.         bcc    1$        ;und ausgeben
  1090.         DATA_HI
  1091.         bra    2$
  1092. 1$        DATA_LO
  1093. 2$
  1094.         bsr    Wait40us    ;Bit set-up talker delay
  1095.  
  1096.         CLOCK_HI        ;Data valid
  1097.  
  1098.         bsr    Wait20us    ;Data valid delay
  1099.  
  1100.         DATA_HI
  1101.         CLOCK_LO
  1102.  
  1103.         dbra    d7,IBOBitLoop    ;Nächstes Bit
  1104.  
  1105. ; 1ms auf Bestätigung warten
  1106.         bsr    Start1ms    ;Timer starten
  1107.  
  1108. IBODACLoop    bsr    TimerDoneQ    ;Timer abgelaufen?
  1109.         bne    IBOTimeOut    ;Ja, dann Time out
  1110.         GET_DATA_CLOCK        ;Auf Listener data accepted warten
  1111.         bcs    IBODACLoop
  1112.  
  1113. ; Alles OK
  1114.         moveq    #ST_OK,d0
  1115.         bra    IBODone
  1116.  
  1117. ; Fehlerbehandlung
  1118. IBODevNotPr    LINE_RELEASE
  1119.         move.b    #ST_NOTPRESENT,d0
  1120.         bra    IBODone
  1121.  
  1122. IBOTimeOut    LINE_RELEASE
  1123.         move.b    #ST_TIMEOUT,d0
  1124.  
  1125. IBODone        JSRLIB    Enable
  1126.  
  1127.         movem.l    (sp)+,a6/d2/d7
  1128.         rts
  1129.  
  1130.  
  1131. *
  1132. * Byte über IEC-Kabel empfangen
  1133. * Rückgabe: d1.b: Empfangenes Byte
  1134. *
  1135.  
  1136. IECByteIn    tst.b    IECIsOpen
  1137.         bne    1$
  1138.         move.b    #ST_NOTPRESENT,d0
  1139.         rts
  1140.  
  1141. 1$        movem.l    d2/d3/d7/a6,-(sp)
  1142.         moveq    #ST_OK,d3    ;d3: Status
  1143.         move.l    _SysBase,a6
  1144.         JSRLIB    Disable
  1145.  
  1146.         CLOCK_HI
  1147.         WAIT_CLOCK_HI
  1148.  
  1149. ; Auf Beginn der Übertragung warten
  1150.         bsr    Start250us    ;Timer starten
  1151.         DATA_HI            ;Listener ready for data
  1152.  
  1153. IBIWaitTalker    bsr    TimerDoneQ    ;Timer abgelaufen?
  1154.         bne    IBIEOI        ;Ja, EOI empfangen
  1155.         GET_DATA_CLOCK        ;Warten auf talker sending
  1156.         bmi    IBIWaitTalker
  1157.         bra    IBIReceive
  1158.  
  1159. ; EOI empfangen, Handshake senden und erneut auf Beginn warten
  1160. IBIEOI        move.b    #ST_EOF,d3
  1161.         DATA_LO            ;EOI handshake
  1162.         CLOCK_HI
  1163.         bsr    Wait60us    ;EOI response hold time
  1164.  
  1165.         bsr    Start250us    ;Timer starten
  1166.         DATA_HI            ;Listener ready for data
  1167.  
  1168. IBIWaitTalker2    bsr    TimerDoneQ    ;Timer abgelaufen?
  1169.         bne    IBITimeOut    ;Ja, dann Time out
  1170.         GET_DATA_CLOCK        ;Warten auf talker sending
  1171.         bmi    IBIWaitTalker2
  1172.  
  1173. ; 8 Bits empfangen
  1174. IBIReceive    moveq    #7,d7        ;d7: Bitzähler
  1175.         moveq    #0,d2        ;d2: Empfangenes Byte
  1176.  
  1177. IBIBitLoop    WAIT_CLOCK_HI        ;Auf Data valid warten
  1178.         roxr.b    #1,d2        ;Datenbit holen
  1179.         WAIT_CLOCK_LO
  1180.         dbra    d7,IBIBitLoop
  1181.  
  1182. ; Empfang bestätigen
  1183.         DATA_LO            ;Listener data accepted
  1184.         btst    #6,d3        ;EOI empfangen?
  1185.         beq    IBIDone
  1186.         LINE_RELEASE        ;Ja, Leitung freigeben
  1187.         bra    IBIDone
  1188.  
  1189. ; Fehlerbehandlung
  1190. IBITimeOut    or.b    #ST_READ_TIMEOUT,d3
  1191.         LINE_RELEASE
  1192.  
  1193. IBIDone        move.b    d3,d0        ;Status holen
  1194.         move.b    d2,d1        ;Byte holen
  1195.         JSRLIB    Enable
  1196.         movem.l    (sp)+,d2/d3/d7/a6
  1197.         rts
  1198.  
  1199.  
  1200. *
  1201. * 20µs/40µs/60µs/1ms warten
  1202. *
  1203.  
  1204. ; Timer auf 20µs setzen
  1205. Wait20us    move.l    CiaControlReg,a0
  1206.         and.b    #$80,(a0)
  1207.         move.l    CiaTimerReg,a0
  1208.         move.b    #14,(a0)
  1209.         move.b    #0,$100(a0)
  1210.         bra    StartTimer
  1211.  
  1212. ; Timer auf 40µs setzen
  1213. Wait40us    move.l    CiaControlReg,a0
  1214.         and.b    #$80,(a0)
  1215.         move.l    CiaTimerReg,a0
  1216.         move.b    #29,(a0)
  1217.         move.b    #0,$100(a0)
  1218.         bra    StartTimer
  1219.  
  1220. ; Timer auf 60µs setzen
  1221. Wait60us    move.l    CiaControlReg,a0
  1222.         and.b    #$80,(a0)
  1223.         move.l    CiaTimerReg,a0
  1224.         move.b    #43,(a0)
  1225.         move.b    #0,$100(a0)
  1226.         bra    StartTimer
  1227.  
  1228. ; Timer auf 1ms setzen
  1229. Wait1ms        move.l    CiaControlReg,a0
  1230.         and.b    #$80,(a0)
  1231.         move.l    CiaTimerReg,a0
  1232.         move.b    #$cc,(a0)
  1233.         move.b    #2,$100(a0)
  1234.         move.l    CiaControlReg,a0
  1235.  
  1236. ; Timer anwerfen (One-Shot) und auf Ablauf warten
  1237. StartTimer    move.l    a6,-(sp)
  1238.         move.l    _CiaBase,a6
  1239.  
  1240.         move.b    WhichTimerMask,d0
  1241.         JSRLIB    SetICR
  1242.  
  1243.         move.l    CiaControlReg,a0
  1244.         move.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1245.  
  1246. 1$        moveq    #0,d0
  1247.         JSRLIB    SetICR
  1248.         and.b    WhichTimerMask,d0
  1249.         beq    1$
  1250.  
  1251.         move.l    (sp)+,a6
  1252.         rts
  1253.  
  1254.  
  1255. *
  1256. * Timer starten, 1ms/250µs
  1257. *
  1258.  
  1259. Start1ms    move.l    a6,-(sp)
  1260.         move.l    _CiaBase,a6
  1261.         move.l    CiaControlReg,a0
  1262.         and.b    #$80,(a0)
  1263.  
  1264.         move.l    CiaTimerReg,a0
  1265.         move.b    #$cc,(a0)
  1266.         move.b    #2,$100(a0)
  1267.  
  1268.         move.b    WhichTimerMask,d0
  1269.         JSRLIB    SetICR
  1270.  
  1271.         move.l    CiaControlReg,a0
  1272.         or.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1273.         move.l    (sp)+,a6
  1274.         rts
  1275.  
  1276. Start250us    move.l    a6,-(sp)
  1277.         move.l    _CiaBase,a6
  1278.         move.l    CiaControlReg,a0
  1279.         and.b    #$80,(a0)
  1280.  
  1281.         move.l    CiaTimerReg,a0
  1282.         move.b    #$b3,(a0)
  1283.         move.b    #0,$100(a0)
  1284.  
  1285.         move.b    WhichTimerMask,d0
  1286.         JSRLIB    SetICR
  1287.  
  1288.         move.l    CiaControlReg,a0
  1289.         or.b    #CIACRAF_LOAD|CIACRAF_RUNMODE|CIACRAF_START,(a0)
  1290.         move.l    (sp)+,a6
  1291.         rts
  1292.  
  1293.  
  1294. *
  1295. * Timer abgelaufen?
  1296. * bne: Ja
  1297. *
  1298.  
  1299. TimerDoneQ    move.l    a6,-(sp)
  1300.         move.l    _CiaBase,a6
  1301.         moveq    #0,d0
  1302.         JSRLIB    SetICR
  1303.         and.b    WhichTimerMask,d0
  1304.         move.l    (sp)+,a6
  1305.         tst.b    d0
  1306.         rts
  1307.  
  1308.  
  1309. *
  1310. * Dummy-Timer-Interrupt-Routine
  1311. *
  1312.  
  1313. IntTimer    moveq    #0,d0
  1314.         rts
  1315.  
  1316.  
  1317. *
  1318. * SetError: 1541-Fehlermeldung bereitstellen
  1319. *
  1320. * a0.l: Zeiger auf DRVDATA
  1321. * d0.l: Fehlercode
  1322. *
  1323.  
  1324.         XDEF    _SetError
  1325. _SetError    move.l    4(sp),a0
  1326.         move.l    8(sp),d0
  1327.         lea    ErrorTab,a1
  1328.         move.l    (a1,d0.l*4),a1
  1329.         move.l    a1,drv_ErrorPtr(a0)
  1330.  
  1331.         move.l    a2,-(sp)
  1332.         move.l    a1,a2
  1333. 1$        tst.b    (a2)+
  1334.         bne    1$
  1335.         sub.l    a1,a2
  1336.         move.l    a2,d0
  1337.         subq.l    #1,d0
  1338.         move.b    d0,drv_ErrorLen(a0)
  1339.         move.l    (sp)+,a2
  1340.         rts
  1341.  
  1342.  
  1343. **
  1344. ** Konstanten
  1345. **
  1346.  
  1347. ; Tabelle für Fehlermeldungen (Index: ErrorCode)
  1348.         CNOP    0,4
  1349. ErrorTab    dc.l    OKText
  1350.         dc.l    WriteErrText
  1351.         dc.l    WriteProtText
  1352.         dc.l    Syntax30Text
  1353.         dc.l    Syntax33Text
  1354.         dc.l    WrFileOpenText
  1355.         dc.l    FileNotOpenText
  1356.         dc.l    FileNotFText
  1357.         dc.l    IllegalTSText
  1358.         dc.l    NoChannelText
  1359.         dc.l    StartupText
  1360.  
  1361. ; Fehlertexte
  1362. OKText        dc.b    "00, OK,00,00",13,0
  1363. WriteErrText    dc.b    "25,WRITE ERROR,00,00",13,0
  1364. WriteProtText    dc.b    "26,WRITE PROTECT ON,00,00",13,0
  1365. Syntax30Text    dc.b    "30,SYNTAX ERROR,00,00",13,0
  1366. Syntax33Text    dc.b    "33,SYNTAX ERROR,00,00",13,0
  1367. WrFileOpenText    dc.b    "60,WRITE FILE OPEN,00,00",13,0
  1368. FileNotOpenText    dc.b    "61,FILE NOT OPEN,00,00",13,0
  1369. FileNotFText    dc.b    "62,FILE NOT FOUND,00,00",13,0
  1370. IllegalTSText    dc.b    "67,ILLEGAL TRACK OR SECTOR,00,00",13,0
  1371. NoChannelText    dc.b    "70,NO CHANNEL,00,00",13,0
  1372. StartupText    dc.b    "73,CBM DOS V2.6 1541,00,00",13,0
  1373.         CNOP    0,4
  1374.  
  1375. ; Tabelle mit Zeigern auf die Laufwerks-Datenstrukturen
  1376.         CNOP    0,4
  1377. DrvTab        dc.l    Drv8Data
  1378.         dc.l    Drv9Data
  1379.         dc.l    Drv10Data
  1380.         dc.l    Drv11Data
  1381.  
  1382. ; Name der temporären Datei für das Directory
  1383. TempFileName    dc.b    "T:Frodo$File",0
  1384.  
  1385. ; Name für AllocMiscResource
  1386. ParPortName    dc.b    "Frodo Parallel Port",0
  1387.  
  1388. ; Name des Timer-Interrupts
  1389. TimerIntName    dc.b    "Frodo Timer Int",0
  1390.         CNOP    0,4
  1391.  
  1392.  
  1393. **
  1394. ** Initialisierte Daten
  1395. **
  1396.  
  1397.         SECTION    "DATA",DATA
  1398.  
  1399. TimerInterrupt    dc.l    0,0
  1400.         dc.b    NT_INTERRUPT,0
  1401.         dc.l    TimerIntName
  1402.         dc.l    0
  1403.         dc.l    IntTimer
  1404.  
  1405.  
  1406. **
  1407. ** Nicht initialisierte Daten
  1408. **
  1409.  
  1410.         SECTION    "BSS",BSS
  1411.  
  1412. ; Global
  1413. ListenerActive    ds.b    1    ;Flag: Listener angewählt, ListenerData ist gültig
  1414. ListenerIsIEC    ds.b    1    ;Flag: Aktiver Listener hängt am IEC-Kabel (impliziert ListenerActive)
  1415. TalkerActive    ds.b    1    ;Flag: Talker angewählt, TalkerData ist gültig
  1416. TalkerIsIEC    ds.b    1    ;Flag: Aktiver Talker hängt am IEC-Kabel (impliziert TalkerActive)
  1417.  
  1418. Listening    ds.b    1    ;Flag: Letzter ATN-Befehl war Listen (für SecListen/SecTalk-Unterscheidung)
  1419. SecAddr        ds.b    1    ;Aktuelle Sekundäradresse ($0x)
  1420. ReceivedCmd    ds.b    1    ;Empfangener Befehlscode ($x0)
  1421.  
  1422. IECIsOpen    ds.b    1    ;Flag: Timer und Port belegt, IEC-Kabel kann benutzt werden
  1423. IECInited    ds.b    1    ;Flag: InitIEC wurde aufgerufen
  1424.  
  1425. WhichTimer    ds.b    1    ;Welcher Timer wurde belegt? (0: Timer A, 1: Timer B)
  1426. WhichTimerMask    ds.b    1    ;Dto. als Bit-Maske für ICR
  1427.  
  1428.         CNOP    0,4
  1429. CiaTimerReg    ds.l    1    ;Zeiger auf Cia-Timer-Register
  1430. CiaControlReg    ds.l    1
  1431.  
  1432. ListenerData    ds.l    1    ;Zeiger auf Struktur des aktiven Listeners
  1433. TalkerData    ds.l    1    ;Zeiger auf Struktur des aktiven Talkers
  1434.  
  1435. DataInBuf    ds.b    1    ;Puffer für DataIn
  1436.  
  1437. ; Datenstruktur pro Laufwerk
  1438.         CNOP    0,4
  1439. Drv8Data    ds.b    drv_SIZEOF
  1440. Drv9Data    ds.b    drv_SIZEOF
  1441. Drv10Data    ds.b    drv_SIZEOF
  1442. Drv11Data    ds.b    drv_SIZEOF
  1443.  
  1444. ; Puffer für Dateinamen/Befehlsstrings
  1445. NameBuf        ds.b    NAMEBUF_LENGTH
  1446.  
  1447. ; Puffer für die Verzeichnisse der 4 Laufwerke
  1448. Dir8        ds.b    256
  1449. Dir9        ds.b    256
  1450. Dir10        ds.b    256
  1451. Dir11        ds.b    256
  1452.  
  1453. ; Einstellungen
  1454. Drv8Type    ds.w    1
  1455. Drv9Type    ds.w    1
  1456. Drv10Type    ds.w    1
  1457. Drv11Type    ds.w    1
  1458. OtherIEC    ds.w    1
  1459.         XDEF    _MapSlash
  1460. _MapSlash
  1461. MapSlash    ds.w    1
  1462.         END
  1463.